﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using CustomControl;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using TeacherLeftHand.DataAccess;
using TeacherLeftHand.Model;
using TeacherLeftHand.Messages;
using TeacherLeftHand.Util;
using TeacherLeftHand.View;

namespace TeacherLeftHand.ViewModel
{
    public class TeachingMethodViewModel : ViewModelBase, IDataErrorInfo
    {
        #region constructor
        public TeachingMethodViewModel()
        {
            _subjectList = new SelectionList<string>(_kiAccessor.GetSubjectList());

            // initialize save command which save the TM to database and broadcast update message
            CreateKIHolderCommand = new RelayCommand<RichTextEditor>(rtbContent =>
                                                         {
                                                             rtbContent.Focus();
                                                             var caretPos = rtbContent.CaretPosition;
                                                             var inlineRtb = new InlineRichTextBox
                                                             {
                                                                 MinWidth = 50,
                                                                 Background = Brushes.LightBlue,
                                                                 IsHitTestVisible = false,
                                                                 HorizontalAlignment =
                                                                     HorizontalAlignment.Stretch
                                                             };
                                                             var container = new InlineUIContainer(
                                                                     inlineRtb,
                                                                     caretPos)
                                                             {
                                                                 BaselineAlignment =
                                                                     BaselineAlignment.Center
                                                             };
                                                             // Set the TextPointer to the end of the current document.
                                                             var moveTo = rtbContent.CaretPosition.GetNextInsertionPosition(LogicalDirection.Forward);

                                                             if (moveTo != null)
                                                             {
                                                                 rtbContent.CaretPosition = moveTo;
                                                             }

                                                         });

            EditCommand = new RelayCommand(() =>
                                               {
                                                   if (IsEditable) return;
                                                   IsEditable = true;
                                                   IsEditButtonEnable = false;
                                                   _originalTM = new TeachingMethod(_teachingMethod);
                                               });

            CancelCommand = new RelayCommand(() =>
                                                 {
                                                     if (!IsEditable) return;
                                                     IsEditable = false;
                                                     IsEditButtonEnable = true;
                                                     _teachingMethod = _originalTM;
                                                     RaisePropertyChanged("PreferredClassLevel");
                                                     RaisePropertyChanged("PreferredSubjectList");
                                                     RaisePropertyChanged("TeamSize");
                                                     RaisePropertyChanged("Tools");
                                                     RaisePropertyChanged("Note");
                                                     RaisePropertyChanged("Name");
                                                     RaisePropertyChanged("Content");
                                                     Messenger.Default.Send(_teachingMethod.Content, "SelectedTMContent");
                                                 });

            SaveCommand = new RelayCommand<RichTextEditor>(rtbContent =>
                                                            {
                                                                //clear context menu before save
                                                                ProcessBeforeSaving(rtbContent);
                                                                _teachingMethod.Content = XamlWriter.Save(rtbContent);
                                                                if (_isCreateNew)
                                                                {
                                                                    _teachingMethod.ID = Add();
                                                                    if (_teachingMethod.ID > 0)
                                                                    {
                                                                        _isCreateNew = false;
                                                                        IsEditButtonEnable = true;
                                                                        IsEditable = false;
                                                                        var msg = new UpdateTMMessage
                                                                        {
                                                                            Action = UpdateAction.
                                                                                               Add,
                                                                            TeachingMethod =
                                                                                _teachingMethod
                                                                        };
                                                                        Messenger.Default.Send(msg);
                                                                    }

                                                                }
                                                                else
                                                                {
                                                                    if (SaveUpdate())
                                                                    {
                                                                        IsEditButtonEnable = true;
                                                                        IsEditable = false;
                                                                        var msg = new UpdateTMMessage
                                                                                      {
                                                                                          Action = UpdateAction.
                                                                                                             Update,
                                                                                          TeachingMethod =
                                                                                              _teachingMethod
                                                                                      };
                                                                        Messenger.Default.Send(msg);
                                                                    }
                                                                }
                                                            },rtb => string.IsNullOrEmpty(Error));

            // initialize delete command which delete the TM from database and broadcast update message
            DeleteCommand = new RelayCommand(() =>
                                                 {
                                                     if (Delete())
                                                     {
                                                         var msg = new UpdateTMMessage
                                                                       {
                                                                           Action = UpdateAction.Delete,
                                                                           TeachingMethod = _teachingMethod
                                                                       };
                                                         Messenger.Default.Send(msg);
                                                     }
                                                 });

            //Register message
            Messenger.Default.Register<TeachingMethod>(this, "SelectedTeachingMethod",
                                                selectedTM =>
                                                {
                                                    if (selectedTM != null)
                                                    {
                                                        _isCreateNew = false;
                                                        _teachingMethod = new TeachingMethod(selectedTM);
                                                        if (_teachingMethod.PreferredSubject != null)
                                                        {
                                                            foreach (var subject in _subjectList)
                                                            {
                                                                subject.IsSelected = _teachingMethod.PreferredSubject.Contains(subject.Item);
                                                            }
                                                        }
                                                        IsEditable = false;
                                                        IsEditButtonEnable = true;
                                                    }
                                                    else
                                                    {
                                                        _teachingMethod = new TeachingMethod();
                                                        SubjectList.UnselectAll();
                                                        IsEditButtonEnable = false;
                                                    }
                                                    RaisePropertyChanged("PreferredClassLevel");
                                                    RaisePropertyChanged("PreferredSubjectList");
                                                    RaisePropertyChanged("SubjectList");
                                                    RaisePropertyChanged("Note");
                                                    RaisePropertyChanged("Name");
                                                    RaisePropertyChanged("Content");

                                                    Messenger.Default.Send(_teachingMethod.Content, "SelectedTMContent");
                                                });

            // register CREATE command 
            Messenger.Default.Register<TeachingMethodViewMessage>(this, Create);
            
        }
        #endregion

        #region properties
        private TeachingMethod _teachingMethod;
        private TeachingMethod _originalTM = new TeachingMethod();
        private readonly KnowledgeItemAccessor _kiAccessor = new KnowledgeItemAccessor();
        private readonly TeachingMethodAccessor _tmAccessor = new TeachingMethodAccessor();
        private SelectionList<string> _subjectList = new SelectionList<string>();
        private bool _isEditButtonEnable;
        private bool _isEditable;
        private bool _isCreateNew;

        public bool IsEditButtonEnable
        {
            get
            {
                if (_teachingMethod == null) return false;
                return _isEditButtonEnable;
            }
            set
            {
                if (_isEditButtonEnable != value)
                {
                    _isEditButtonEnable = value;
                    RaisePropertyChanged("IsEditButtonEnable");
                }
            }
        }

        public bool IsEditable
        {
            get
            {
                if (_teachingMethod == null) return false;
                return _isEditable;
            }
            set
            {
                if (_isEditable != value)
                {
                    _isEditable = value;
                    RaisePropertyChanged("IsEditable");
                }
            }
        }

        public SelectionList<string> SubjectList
        {
            get
            {
                return _subjectList;
            }
            set
            {
                _subjectList = value;
                foreach (var selectionItem in value)
                {
                    if (selectionItem.IsSelected)
                    {
                        if (!_teachingMethod.PreferredSubject.Contains(selectionItem.Item))
                        {
                            _teachingMethod.PreferredSubject.Add(selectionItem.Item);
                        }
                    }
                    else
                    {
                        if (_teachingMethod.PreferredSubject.Contains(selectionItem.Item))
                        {
                            _teachingMethod.PreferredSubject.Remove(selectionItem.Item);
                        }
                    }

                }
                RaisePropertyChanged("SubjectList");
            }
        }



        public ObservableCollection<int> ClassLevelList
        {
            get { return DataHelper.ClassLevelList; }
        }

        /// <summary>
        /// Content of the TM
        /// </summary>
        public string Content
        {
            get
            {
                if (_teachingMethod == null) return "";
                return _teachingMethod.Content;
            }
            set
            {
                if (_teachingMethod.Content != value)
                {
                    _teachingMethod.Content = value;
                    RaisePropertyChanged("Content");
                }
            }
        }

        /// <summary>
        /// TM name
        /// </summary>
        public string Name
        {
            get
            {
                if (_teachingMethod == null) return "";
                return _teachingMethod.Name;
            }
            set
            {
                if (_teachingMethod.Name != value)
                {
                    _teachingMethod.Name = value;
                    RaisePropertyChanged("Name");
                }
            }
        }

        /// <summary>
        /// TM note
        /// </summary>
        public string Note
        {
            get
            {
                if (_teachingMethod == null) return "";
                return _teachingMethod.Note;
            }
            set
            {
                if (_teachingMethod.Note != value)
                {
                    _teachingMethod.Note = value;
                    RaisePropertyChanged("Note");
                }
            }
        }

        /// <summary>
        /// Preferred class level for this TM
        /// </summary>
        public int PreferredClassLevel
        {
            get
            {
                if (_teachingMethod == null) return 0;
                return _teachingMethod.PreferredClassLevel;
            }
            set
            {
                if (_teachingMethod.PreferredClassLevel != value)
                {
                    _teachingMethod.PreferredClassLevel = value;
                    RaisePropertyChanged("PreferredClassLevel");

                }
            }
        }

        #region Commands
        public ICommand CancelCommand
        {
            get;
            private set;
        }

        public ICommand EditCommand
        {
            get;
            private set;
        }

        public ICommand CreateKIHolderCommand
        {
            get;
            private set;
        }

        /// <summary>
        /// Save Command, bind to the Save button or context menu
        /// </summary>
        public RelayCommand<RichTextEditor> SaveCommand
        {
            get;
            private set;
        }

        /// <summary>
        /// Delete Command, bind to the Delete Button or Context Menu
        /// </summary>
        public ICommand DeleteCommand
        {
            get;
            private set;
        }

        /// <summary>
        /// Update Command, bind to the Update Button or Context Menu
        /// </summary>
        public ICommand UpdateCommand
        {
            get;
            private set;
        }
        #endregion



        #endregion

        #region Implementation of IDataErrorInfo

        /// <summary>
        /// Gets the error message for the property with the given name.
        /// </summary>
        /// <returns>
        /// The error message for the property. The default is an empty string ("").
        /// </returns>
        /// <param name="columnName">The name of the property whose error message to get. </param>
        public string this[string columnName]
        {
            get
            {
                var msg = "";
                if (IsEditable)
                {
                    switch (columnName)
                    {
                            // name is required _activity
                        case "Name":
                            if (string.IsNullOrEmpty(Name))
                            {
                                msg = "Required _activity";
                            }
                            break;
                        default:
                            throw new ArgumentException(
                                "Unrecognized property: " + columnName);
                    }
                }
                return msg;
            }
        }

        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        /// <returns>
        /// An error message indicating what is wrong with this object. The default is an empty string ("").
        /// </returns>
        public string Error
        {
            get { return string.Empty; }
        }

        #endregion

        #region methods
        /// <summary>
        /// Add this new Teaching Method to the database
        /// </summary>
        public bool SaveUpdate()
        {
            // get preferredsubject
            _teachingMethod.PreferredSubject.Clear();
            foreach (var subject in _subjectList)
            {
                if (subject.IsSelected)
                {
                    _teachingMethod.PreferredSubject.Add(subject.Item);
                }
            }
            return _tmAccessor.Update(_teachingMethod);
        }

        private int Add()
        {
            // get preferredsubject
            _teachingMethod.PreferredSubject.Clear();
            foreach (var subject in _subjectList)
            {
                if (subject.IsSelected)
                {
                    _teachingMethod.PreferredSubject.Add(subject.Item);
                }
            }
            return _tmAccessor.Add(_teachingMethod);
        }

        /// <summary>
        /// Delete the current Teaching Method
        /// </summary>
        public bool Delete()
        {
            return _tmAccessor.Delete(_teachingMethod);
        }

        private static void ProcessBeforeSaving(RichTextEditor richTextEditor)
        {
            richTextEditor.ClearValue(RichTextEditor.ContextMenuProperty);
            foreach (var block in richTextEditor.Document.Blocks)
            {
                //if (b is Paragraph)
                //{
                //    foreach (Inline i in ((Paragraph)b).Inlines)
                //    {
                //        var inlineType = i.GetType();
                     
                //        if (inlineType == typeof(InlineUIContainer))
                //        {
                //            //The inline has an object, likely an IMAGE!!!
                //            var uic = ((InlineUIContainer)i);
                           
                //            if (uic.Child.GetType() == typeof(InlineRichTextBox))
                //            {
                //                var temp = (InlineRichTextBox)uic.Child;
                //                temp.ClearValue(RichTextEditor.ContextMenuProperty);
                //            }
                //            if (inlineType == typeof(Span))
                //            {
                //                foreach (var ninline in ((Span)i).Inlines)
                //                {
                //                    if (ninline is InlineUIContainer)
                //                    {
                //                        var child = ((InlineUIContainer)ninline).Child;
                //                        if (child is InlineRichTextBox)
                //                        {
                //                            var temp = (InlineRichTextBox)child;
                //                            temp.ClearValue(RichTextEditor.ContextMenuProperty);
                //                        }
                //                    }
                //                }
                //            }
                //        }

                //    }
                //}
                     Utility.ProcessBeforeSaving(block);
            }
        }
     
        private void Create(TeachingMethodViewMessage msg)
        {
            _isCreateNew = true;
            _teachingMethod = new TeachingMethod();
            _originalTM = new TeachingMethod();

            if (!IsEditable)
            {
                IsEditable = true;
                IsEditButtonEnable = false;
            }

            RaisePropertyChanged("PreferredClassLevel");
            RaisePropertyChanged("PreferredSubjectList");
            RaisePropertyChanged("TeamSize");
            RaisePropertyChanged("Tools");
            RaisePropertyChanged("Note");
            RaisePropertyChanged("Name");
            RaisePropertyChanged("Content");

            SubjectList.UnselectAll();

            Messenger.Default.Send("", "SelectedTMContent");

          
        }

        #endregion
    }
}
